1 Xenium Human Breast Gene Expression

1.1 Preprocessing & Cell annotation

path <- "./../10X_Xenium_sample/Xenium_V1_human_Breast_2fov_outs/"
data_name = stringr::str_split(path, "/")[[1]][length(stringr::str_split(path, "/")[[1]])-1]
dir.create(paste0("./output/figure/",figure_dir,"/",data_name), showWarnings = FALSE)

# Load the Xenium data
data <- ReadXenium(path, outs = c("matrix", "microns"), type = c("centroids", "segmentations"))
## continue the regular LoadXenium
segmentations.data <- list(
  centroids = CreateCentroids(data$centroids),
  segmentation = CreateSegmentation(data$segmentations))
coords <- CreateFOV(
  coords = segmentations.data, 
  type = c("segmentation", "centroids"), 
  molecules = data$microns, 
  assay = "Spatial")
xenium.obj <- CreateSeuratObject(
  counts = data$matrix[["Gene Expression"]], 
  assay = "Spatial")
xenium.obj[["BlankCodeword"]] <- CreateAssayObject(counts = data$matrix[["Unassigned Codeword"]])
xenium.obj[["ControlCodeword"]] <- CreateAssayObject(counts = data$matrix[["Negative Control Codeword"]])
xenium.obj[["ControlProbe"]] <- CreateAssayObject(counts = data$matrix[["Negative Control Probe"]])
xenium.obj[["fov"]] <- coords
rm(data); gc(); gc()
##            used  (Mb) gc trigger   (Mb) limit (Mb) max used   (Mb)
## Ncells 15622688 834.4   24461250 1306.4         NA 24461250 1306.4
## Vcells 31214336 238.2   59605184  454.8      49152 59605184  454.8
##            used  (Mb) gc trigger   (Mb) limit (Mb) max used   (Mb)
## Ncells 15622858 834.4   24461250 1306.4         NA 24461250 1306.4
## Vcells 31214780 238.2   59605184  454.8      49152 59605184  454.8
rm(coords); gc(); gc()
##            used  (Mb) gc trigger   (Mb) limit (Mb) max used   (Mb)
## Ncells 15360908 820.4   24461250 1306.4         NA 24461250 1306.4
## Vcells 30483795 232.6   59605184  454.8      49152 59605184  454.8
##            used  (Mb) gc trigger   (Mb) limit (Mb) max used   (Mb)
## Ncells 15360914 820.4   24461250 1306.4         NA 24461250 1306.4
## Vcells 30483889 232.6   59605184  454.8      49152 59605184  454.8
rm(segmentations.data); gc(); gc()
##            used  (Mb) gc trigger   (Mb) limit (Mb) max used   (Mb)
## Ncells 15120794 807.6   24461250 1306.4         NA 24461250 1306.4
## Vcells 29767453 227.2   59605184  454.8      49152 59605184  454.8
##            used  (Mb) gc trigger   (Mb) limit (Mb) max used   (Mb)
## Ncells 15120800 807.6   24461250 1306.4         NA 24461250 1306.4
## Vcells 29767547 227.2   59605184  454.8      49152 59605184  454.8
xenium.obj <- subset(xenium.obj, subset = nCount_Spatial > 0)

print(dim(xenium.obj@assays$Spatial$counts))
## [1]  280 7273
xenium.obj@assays$Spatial$counts[1:5,1:5]
## 5 x 5 sparse Matrix of class "dgCMatrix"
##        aaaiikim-1 aaaljapa-1 aabhbgmg-1 aabpgobe-1 aacemgol-1
## ABCC11          .          .          .          .          .
## ACTA2           1          .          .          .          .
## ACTG2           .          .          .          .          .
## ADAM9           1          .          2          1          .
## ADGRE5          .          .          .          .          .
head(xenium.obj@meta.data)
##               orig.ident nCount_Spatial nFeature_Spatial nCount_BlankCodeword
## aaaiikim-1 SeuratProject             66               32                    0
## aaaljapa-1 SeuratProject             95               43                    0
## aabhbgmg-1 SeuratProject            215               74                    0
## aabpgobe-1 SeuratProject            103               42                    0
## aacemgol-1 SeuratProject             95               49                    0
## aacnljfi-1 SeuratProject            146               56                    0
##            nFeature_BlankCodeword nCount_ControlCodeword
## aaaiikim-1                      0                      0
## aaaljapa-1                      0                      0
## aabhbgmg-1                      0                      0
## aabpgobe-1                      0                      0
## aacemgol-1                      0                      0
## aacnljfi-1                      0                      0
##            nFeature_ControlCodeword nCount_ControlProbe nFeature_ControlProbe
## aaaiikim-1                        0                   0                     0
## aaaljapa-1                        0                   0                     0
## aabhbgmg-1                        0                   0                     0
## aabpgobe-1                        0                   0                     0
## aacemgol-1                        0                   0                     0
## aacnljfi-1                        0                   0                     0
summary(xenium.obj@meta.data$nCount_Spatial)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##     1.0    54.0   109.0   123.3   174.0   673.0
summary(xenium.obj@meta.data$nFeature_Spatial)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##    1.00   31.00   46.00   44.66   59.00  112.00
VlnPlot(xenium.obj, features = c("nFeature_Spatial", "nCount_Spatial"), ncol = 2, pt.size = 0)

ImageDimPlot(xenium.obj, fov = "fov", molecules = c("TUBB2B", "PELI1", "CENPF", "KRT23","PDGFRB","ITGAX","KRT14","GZMA"), nmols = 20000)

xenium.obj <- SCTransform(xenium.obj, assay = "Spatial",
                          conserve.memory = TRUE, vst.flavor="v2")
## 
  |                                                                            
  |                                                                      |   0%
  |                                                                            
  |===================================                                   |  50%
  |                                                                            
  |======================================================================| 100%
xenium.obj <- RunPCA(xenium.obj, assay = "SCT", verbose = FALSE)
xenium.obj <- FindNeighbors(xenium.obj, 
                     reduction = "pca", 
                     k.param = 30,
                     dims = 1:30)
xenium.obj <- RunUMAP(xenium.obj, 
               reduction = "pca", 
               n.neighbors = 30L,
               min.dist = 0.3,
               dims = 1:30)

print("Clustering...")
## [1] "Clustering..."
# Louvain
snn_pcs <- BuildSNNSeurat(xenium.obj[["pca"]]@cell.embeddings[,1:30], 
                          nn.eps = 0)

resolution_list <- c(0.2, 0.4, 0.6, 0.8, 1.0)
ids_cos <- Reduce(cbind, parallel::mclapply(resolution_list, function(res_use) {
  Seurat:::RunModularityClustering(SNN = snn_pcs, 
                                   modularity = 1, 
                                   resolution = res_use, 
                                   algorithm = 3, 
                                   n.start = 10, 
                                   n.iter = 10, random.seed = 0, print.output = FALSE, 
                                   temp.file.location = NULL, edge.file.name = NULL)    
}, mc.cores = min(16, length(resolution_list))))
ids_cos %<>% data.frame()
colnames(ids_cos) <- sprintf("res_%.2f", resolution_list)

ids_cos$res_0.20 <- as.character(ids_cos$res_0.20)
ids_cos$res_0.40 <- as.character(ids_cos$res_0.40)
ids_cos$res_0.60 <- as.character(ids_cos$res_0.60)
ids_cos$res_0.80 <- as.character(ids_cos$res_0.80)
ids_cos$res_1.00 <- as.character(ids_cos$res_1.00)

rownames(ids_cos) = rownames(xenium.obj@meta.data)
ids_cos <- ids_cos %>%
  dplyr::mutate(across(everything(), ~ factor(.x, levels = sort(unique(.x)))))
xenium.obj <- AddMetaData(xenium.obj, ids_cos)
head(xenium.obj@meta.data)
##               orig.ident nCount_Spatial nFeature_Spatial nCount_BlankCodeword
## aaaiikim-1 SeuratProject             66               32                    0
## aaaljapa-1 SeuratProject             95               43                    0
## aabhbgmg-1 SeuratProject            215               74                    0
## aabpgobe-1 SeuratProject            103               42                    0
## aacemgol-1 SeuratProject             95               49                    0
## aacnljfi-1 SeuratProject            146               56                    0
##            nFeature_BlankCodeword nCount_ControlCodeword
## aaaiikim-1                      0                      0
## aaaljapa-1                      0                      0
## aabhbgmg-1                      0                      0
## aabpgobe-1                      0                      0
## aacemgol-1                      0                      0
## aacnljfi-1                      0                      0
##            nFeature_ControlCodeword nCount_ControlProbe nFeature_ControlProbe
## aaaiikim-1                        0                   0                     0
## aaaljapa-1                        0                   0                     0
## aabhbgmg-1                        0                   0                     0
## aabpgobe-1                        0                   0                     0
## aacemgol-1                        0                   0                     0
## aacnljfi-1                        0                   0                     0
##            nCount_SCT nFeature_SCT res_0.20 res_0.40 res_0.60 res_0.80 res_1.00
## aaaiikim-1        112           33        0        2        2        2        1
## aaaljapa-1        107           43        0        2        0        2        1
## aabhbgmg-1        139           69        0        3        3        3        1
## aabpgobe-1        111           42        0        0        0        2        1
## aacemgol-1        106           49        0        3        3        3        3
## aacnljfi-1        132           56        0        0        0        2        1
resolution = "0.60"
Idents(xenium.obj) = xenium.obj@meta.data[,paste0("res_",resolution)]

cluster_col = paste0("res_",resolution)
g = CellDimPlot(
  srt = xenium.obj, 
  group.by = cluster_col, 
  reduction = "UMAP", theme_use = "theme_blank",
  raster = FALSE,
  stat_plot_size = 3
) 
g 

xenium.obj.markers <- FindAllMarkers(xenium.obj, only.pos = TRUE)
xenium.obj.markers %>%
  group_by(cluster) %>%
  dplyr::slice_max(avg_log2FC, n = 10) %>%
  as.data.frame() 
##            p_val avg_log2FC pct.1 pct.2     p_val_adj cluster     gene
## 1  2.662899e-144  1.1679022 0.672 0.333 7.456118e-142       0   TUBB2B
## 2   9.566100e-58  1.1014546 0.297 0.131  2.678508e-55       0     CAV1
## 3   4.131144e-47  1.0423056 0.288 0.138  1.156720e-44       0   MYBPC1
## 4   1.174734e-09  0.9748890 0.065 0.032  3.289254e-07       0   SERHL2
## 5   5.652455e-83  0.8908141 0.614 0.365  1.582687e-80       0   SLC5A6
## 6  5.093635e-147  0.8779398 0.862 0.585 1.426218e-144       0    CCND1
## 7   4.594085e-54  0.8503573 0.450 0.255  1.286344e-51       0    TRAF4
## 8   6.618904e-26  0.8189392 0.236 0.131  1.853293e-23       0   PTRHD1
## 9  1.403824e-215  0.7650828 0.999 0.890 3.930707e-213       0     AQP1
## 10  7.102044e-03  0.7501358 0.020 0.011  1.000000e+00       0 APOBEC3A
## 11  0.000000e+00  3.0765049 0.955 0.291  0.000000e+00       1    TOP2A
## 12  0.000000e+00  2.7393502 0.719 0.176  0.000000e+00       1    CENPF
## 13  0.000000e+00  2.6929152 0.877 0.266  0.000000e+00       1    MKI67
## 14 1.834973e-179  2.1395594 0.475 0.126 5.137924e-177       1    RTKN2
## 15 6.780687e-134  1.9392679 0.412 0.119 1.898592e-131       1    PCLAF
## 16  3.384295e-47  0.8499877 0.593 0.385  9.476026e-45       1   TUBB2B
## 17  3.258181e-13  0.7497524 0.185 0.108  9.122906e-11       1    FOXC2
## 18  3.059700e-07  0.6872314 0.102 0.060  8.567159e-05       1     TCF7
## 19  6.658867e-33  0.6227176 0.644 0.466  1.864483e-30       1 EIF4EBP1
## 20  9.353109e-12  0.6102920 0.273 0.186  2.618870e-09       1  ANKRD28
## 21 3.338556e-168  3.2232114 0.284 0.042 9.347957e-166       2    KRT23
## 22  1.182827e-14  3.1600350 0.029 0.005  3.311916e-12       2     KRT5
## 23  2.419718e-54  2.4714986 0.144 0.033  6.775211e-52       2    KRT14
## 24 1.462371e-127  2.3292966 0.301 0.064 4.094640e-125       2     KLF5
## 25  5.715703e-55  2.2236511 0.139 0.030  1.600397e-52       2     MLPH
## 26  1.373781e-11  2.2141908 0.037 0.010  3.846588e-09       2  S100A14
## 27 7.226854e-177  1.7475072 0.706 0.299 2.023519e-174       2      KIT
## 28  2.408642e-15  1.7219561 0.071 0.025  6.744196e-13       2     MUC6
## 29  2.346541e-20  1.7013104 0.102 0.037  6.570315e-18       2    CLIC6
## 30 6.904015e-144  1.6591053 0.666 0.306 1.933124e-141       2    CXCR4
## 31  1.372517e-09  0.3277354 0.819 0.710  3.843048e-07       3    PELI1
## 32  4.281185e-03  0.1577536 0.180 0.240  1.000000e+00       3    HOOK2
## 33  2.329050e-03  0.1564239 0.209 0.280  6.521341e-01       3      JUP
## 34  4.800788e-04  0.1394539 0.127 0.186  1.344221e-01       3  DNTTIP1
## 35  1.246445e-03  0.1231136 1.000 0.948  3.490046e-01       3     LDHB
## 36  0.000000e+00  2.5600975 1.000 0.510  0.000000e+00       4 SERPINA3
## 37  8.206200e-03  1.5294855 0.010 0.003  1.000000e+00       4    ADH1B
## 38  9.341991e-05  1.0418794 0.033 0.014  2.615758e-02       4     SPIB
## 39  8.069967e-17  0.9086068 0.241 0.132  2.259591e-14       4    DUSP2
## 40  4.189243e-52  0.8097979 0.717 0.464  1.172988e-49       4 EIF4EBP1
## 41  1.619078e-20  0.7109335 0.432 0.279  4.533418e-18       4     WARS
## 42  2.597619e-44  0.6878823 0.658 0.386  7.273332e-42       4   TUBB2B
## 43  3.768419e-29  0.6653245 0.579 0.374  1.055157e-26       4     SQLE
## 44  3.184379e-04  0.6438372 0.089 0.058  8.916261e-02       4    MYO5B
## 45  1.085285e-42  0.6417512 0.821 0.604  3.038797e-40       4   SEC11C
## 46  0.000000e+00  4.6918879 0.504 0.032  0.000000e+00       5   LRRC15
## 47  0.000000e+00  4.5836602 0.468 0.029  0.000000e+00       5   PDGFRB
## 48  0.000000e+00  4.5139079 0.919 0.156  0.000000e+00       5    POSTN
## 49  0.000000e+00  4.4042333 0.948 0.184  0.000000e+00       5      LUM
## 50  0.000000e+00  4.3352375 0.814 0.110  0.000000e+00       5    SFRP4
## 51 3.304544e-203  4.2674955 0.252 0.018 9.252723e-201       5  C5orf46
## 52  0.000000e+00  4.1969031 0.790 0.104  0.000000e+00       5   CXCL12
## 53  0.000000e+00  4.1827769 0.692 0.066  0.000000e+00       5   CCDC80
## 54 1.416108e-286  3.9928945 0.407 0.040 3.965103e-284       5     GJB2
## 55 3.081503e-185  3.9617716 0.247 0.020 8.628209e-183       5     IGF1
## 56  0.000000e+00  5.5070742 0.646 0.030  0.000000e+00       6    ITGAX
## 57 2.314770e-296  5.1912226 0.293 0.011 6.481356e-294       6    ITGAM
## 58  0.000000e+00  4.9972590 0.559 0.031  0.000000e+00       6    CD163
## 59  0.000000e+00  4.8843382 0.431 0.019  0.000000e+00       6     C1QA
## 60  0.000000e+00  4.8189677 0.887 0.121  0.000000e+00       6      LYZ
## 61  0.000000e+00  4.6206767 0.521 0.031  0.000000e+00       6    IGSF6
## 62  0.000000e+00  4.6107789 0.913 0.106  0.000000e+00       6   FCER1G
## 63  0.000000e+00  4.5730583 0.530 0.034  0.000000e+00       6   FCGR3A
## 64  0.000000e+00  4.5628294 0.833 0.096  0.000000e+00       6     CD68
## 65  0.000000e+00  4.5618335 0.480 0.028  0.000000e+00       6     C1QC
## 66 3.031048e-133  6.8417162 0.173 0.003 8.486933e-131       7     PRF1
## 67  0.000000e+00  6.2092815 0.835 0.029  0.000000e+00       7     CD3E
## 68  0.000000e+00  6.2038023 0.551 0.016  0.000000e+00       7     GZMA
## 69  0.000000e+00  6.1773328 0.764 0.025  0.000000e+00       7     TRAC
## 70 3.158396e-292  6.1292220 0.583 0.022 8.843508e-290       7     CCL5
## 71 4.485128e-230  6.1066864 0.354 0.009 1.255836e-227       7    CD247
## 72  3.283038e-61  6.0487008 0.079 0.001  9.192507e-59       7     GZMK
## 73  9.214896e-60  6.0236889 0.102 0.003  2.580171e-57       7     GNLY
## 74 1.057008e-139  5.8774293 0.244 0.007 2.959622e-137       7     CD69
## 75 9.851276e-104  5.6622324 0.189 0.006 2.758357e-101       7     NKG7
## 76  0.000000e+00  7.7631017 0.800 0.008  0.000000e+00       8  CLEC14A
## 77  0.000000e+00  7.7159366 0.900 0.016  0.000000e+00       8      VWF
## 78  0.000000e+00  6.7682404 0.686 0.012  0.000000e+00       8      KDR
## 79  0.000000e+00  6.7405943 0.629 0.011  0.000000e+00       8    MMRN2
## 80 2.475225e-167  6.7309029 0.257 0.003 6.930631e-165       8     ESM1
## 81 1.157115e-114  6.6070967 0.171 0.002 3.239923e-112       8    SOX18
## 82 2.358859e-121  6.4735951 0.186 0.002 6.604804e-119       8    IL3RA
## 83 1.108004e-198  6.2414925 0.386 0.007 3.102411e-196       8    HOXD9
## 84 1.893055e-291  6.2061499 0.900 0.035 5.300555e-289       8     CD93
## 85 4.691615e-108  6.1590304 0.214 0.004 1.313652e-105       8  NOSTRIN

Cluster annotation: 0 Basal-like epithelial cells / Myoepithelial cells 1 Proliferating epithelial cells 2 Basal/myoepithelial tumor cells 3 Unclassified immune-like cells 4 Inflammatory immune cells (e.g. B cells / monocytes) 5 Cancer-associated fibroblasts (CAFs) 6 Macrophages (TAMs) 7 Cytotoxic / Activated T cells 8 Endothelial cells

table(xenium.obj@meta.data[,cluster_col])
## 
##    0    1    2    3    4    5    6    7    8 
## 1794 1125 1060  906  827  754  610  127   70
xenium.obj@meta.data$new_cluster = dplyr::case_when(
  xenium.obj@meta.data[,cluster_col] == "0" ~ "BasalMyo_epithelial_cells",
  xenium.obj@meta.data[,cluster_col] == "1" ~ "Proliferating_epithelial_cells",
  xenium.obj@meta.data[,cluster_col] == "2" ~ "BasalMyo_tumor_cells",
  xenium.obj@meta.data[,cluster_col] == "3" ~ "Unclassified_immune-like_cells",
  xenium.obj@meta.data[,cluster_col] == "4" ~ "Inflammatory_immune_cells",
  xenium.obj@meta.data[,cluster_col] == "5" ~ "Cancer-associated_fibroblasts",
  xenium.obj@meta.data[,cluster_col] == "6" ~ "Tumor-associated_macrophages",
  xenium.obj@meta.data[,cluster_col] == "7" ~ "Cytotoxic_T",
  xenium.obj@meta.data[,cluster_col] == "8" ~ "Endothelial_cells"
)
table(xenium.obj@meta.data$new_cluster)
## 
##      BasalMyo_epithelial_cells           BasalMyo_tumor_cells 
##                           1794                           1060 
##  Cancer-associated_fibroblasts                    Cytotoxic_T 
##                            754                            127 
##              Endothelial_cells      Inflammatory_immune_cells 
##                             70                            827 
## Proliferating_epithelial_cells   Tumor-associated_macrophages 
##                           1125                            610 
## Unclassified_immune-like_cells 
##                            906
cluster_col = "new_cluster"
Idents(xenium.obj) = xenium.obj@meta.data$new_cluster
cluster_COLORS = manual_colors
names(cluster_COLORS) = levels(Idents(xenium.obj))
cluster_COLORS = na.omit(cluster_COLORS)
g = CellDimPlot(
  srt = xenium.obj, 
  group.by = cluster_col, 
  reduction = "UMAP", theme_use = "theme_blank",
  raster = FALSE,
  stat_plot_size = 1
) &
  scale_color_manual(values = cluster_COLORS) &
  guides(color = guide_legend(override.aes = list(size=5,
                                                 alpha = 1),
                             title = "cluster",
                             ncol = 1))
g 

ggsave(paste0("./output/figure/",figure_dir,"/",data_name,"/CellDimPlot.pdf"), g, width=7, height=4, dpi=300)
g = ImageDimPlot(xenium.obj,
             fov = "fov", 
             size = 1.2,
             group.by = cluster_col, 
             dark.background = F)  &
  scale_fill_manual(values = cluster_COLORS) &
  guides(fill = guide_legend(override.aes = list(size=5,
                                                 alpha = 1),
                             title = "cluster",
                             ncol = 1))
g 

ggsave(paste0("./output/figure/",figure_dir,"/",data_name,"/ImageDimPlot_byClusters.pdf"), g, width=6, height=4, dpi=300)

print(xenium.obj)
## An object of class Seurat 
## 821 features across 7273 samples within 5 assays 
## Active assay: SCT (280 features, 280 variable features)
##  3 layers present: counts, data, scale.data
##  4 other assays present: Spatial, BlankCodeword, ControlCodeword, ControlProbe
##  2 dimensional reductions calculated: pca, umap
##  1 spatial field of view present: fov

1.2 Spatial neighborhood analysis (SNA, cell type level analysis)

n_perm = 100
neighbors.k_ = 30 # Number of neighbors to search
seed = 1234

start_time = Sys.time()
xenium.obj <- nhood_enrichment(
  xenium.obj,
  cluster_key = cluster_col, 
  neighbors.k = neighbors.k_, 
  connectivity_key = "nn", 
  transformation = TRUE,
  n_perms = n_perm, seed = seed, n_jobs = 4
)
end_time = Sys.time()
print("Elapsed time:")
## [1] "Elapsed time:"
difftime(end_time, start_time, units = "secs")
## Time difference of 10.09798 secs
mat = xenium.obj@misc[[paste0(cluster_col,"_nhood_enrichment")]]$zscore
colnames(mat) = gsub("^Cluster","",colnames(mat))
rownames(mat) = gsub("^Cluster","",rownames(mat))

pval_mat <- 1 - pnorm(mat)
# 行列をベクトルにし、一括で多重検定補正
# → 元の行列次元に再度変形
fdr_vec <- p.adjust(as.vector(pval_mat), method = "BH")
fdr_mat <- matrix(fdr_vec, nrow=nrow(mat), ncol=ncol(mat),
                  dimnames = dimnames(mat))
# --- 3) FDR<0.05 なら `*` を付与 ---
sig_mat <- ifelse(fdr_mat < 0.05, "**", ifelse(fdr_mat > 0.05 & fdr_mat < 0.1, "*", ""))

common_names <- intersect(rownames(mat), colnames(mat))
for (nm in common_names) {
  mat[nm, nm] <- NA
  sig_mat[nm, nm] <- ""
}

heatmap <- Heatmap(mat,
                   name = "Z-score",
                   col = colorRamp2(c(-2, 0, 2), c("#0072B5FF", "white", "#BC3C29FF")), 
                   show_row_names = TRUE, 
                   show_column_names = TRUE,  
                   cluster_rows = TRUE,  
                   cluster_columns = TRUE,  
                   #show_column_dend = FALSE,
                   #show_row_dend = FALSE,
                   row_title = "",  
                   column_title = paste0("Spatial Neigborhood Enrichment\n",data_name),
                   rect_gp = gpar(col = "black", lwd = 0.3),
                   na_col = "black",          # ← NA を黒色で塗りつぶす
                   column_names_gp = grid::gpar(fontsize = 10),
                   row_names_gp = grid::gpar(fontsize = 10),
                   # cell_fun で各セルに注釈を描く
                   cell_fun = function(j, i, x, y, width, height, fill) {
                     if(sig_mat[i, j] == "**") {
                       grid.text("**", 
                                 x = x,
                                 y = y - 0.2 * height,  # 中心より下にオフセット, 
                                 gp = gpar(fontsize = 15, col = "white", fontface = "bold"))
                     }
                     if(sig_mat[i, j] == "*") {
                       grid.text("*", 
                                 x = x,
                                 y = y - 0.2 * height,  # 中心より下にオフセット, 
                                 gp = gpar(fontsize = 15, col = "white", fontface = "bold"))
                     }
                   }
)

#pdf(paste0("./output/figure/",figure_dir,"/",data_name,"/SNA_heatmap.pdf"), width=4.5, height=5.5)
draw(heatmap, 
     merge_legend = TRUE,
     heatmap_legend_side = "bottom", 
     annotation_legend_side = "bottom")

#dev.off()

1.3 Spatial co-localization score (sCLA, cell-cell level analysis)

cluster_x <- "Cytotoxic_T"
cluster_y <- "Cancer-associated_fibroblasts"
table(Idents(xenium.obj))
## 
##           BasalMyo_tumor_cells      BasalMyo_epithelial_cells 
##                           1060                           1794 
## Unclassified_immune-like_cells Proliferating_epithelial_cells 
##                            906                           1125 
##   Tumor-associated_macrophages                    Cytotoxic_T 
##                            610                            127 
##  Cancer-associated_fibroblasts              Endothelial_cells 
##                            754                             70 
##      Inflammatory_immune_cells 
##                            827
radius_ = 30 # Radius to search for neighbors (µm, cell_type_2) around anchor cells (cell_type_1)

start_time = Sys.time()
cooccur_local_df <- cooccur_local(
  xenium.obj,
  cluster_key      = cluster_col,
  sample_key       = NULL,
  cluster_x        = cluster_x,
  cluster_y        = cluster_y,
  connectivity_key = "nn",
  neighbors.k      = neighbors.k_, 
  radius           = radius_,
  maxnsteps        = 15
)
end_time = Sys.time()
print("Elapsed time:")
## [1] "Elapsed time:"
difftime(end_time, start_time, units = "secs")
## Time difference of 1.683462 secs
summary(cooccur_local_df)
##  cooccur_local_Cytotoxic_T_Cancer-associated_fibroblasts
##  Min.   :0.00000                                        
##  1st Qu.:0.00000                                        
##  Median :0.00000                                        
##  Mean   :0.11811                                        
##  3rd Qu.:0.03125                                        
##  Max.   :1.13205
xenium.obj = AddMetaData(xenium.obj, cooccur_local_df)

g = ImageFeaturePlot(xenium.obj, 
                     features = paste0("cooccur_local_",cluster_x,"_",cluster_y), 
                     #dark.background = F,
                     cols = c("white", "red"))
g

ggsave(paste0("./output/figure/",figure_dir,"/",data_name,"/ImageFeaturePlot_",cluster_x,"_",cluster_y,".pdf"), g, width=6, height=4, dpi=300)



2 Xenium Mouse Brain

2.1 Preprocessing & Cell annotation

path <- "./../10X_Xenium_sample/Xenium_V1_FF_Mouse_Brain_Coronal_Subset_CTX_HP_outs/"
data_name = stringr::str_split(path, "/")[[1]][length(stringr::str_split(path, "/")[[1]])-1]
dir.create(paste0("./output/figure/",figure_dir,"/",data_name), showWarnings = FALSE)

xenium.obj <- LoadXenium(path, fov = "fov")
# remove cells with 0 counts
xenium.obj <- subset(xenium.obj, subset = nCount_Xenium > 0)

VlnPlot(xenium.obj, features = c("nFeature_Xenium", "nCount_Xenium"), ncol = 2, pt.size = 0)

ImageDimPlot(xenium.obj, 
             fov = "fov", 
             size = 0.5,
             molecules = c("Gad1", "Sst", "Pvalb", "Gfap"), nmols = 20000)

xenium.obj <- SCTransform(xenium.obj, assay = "Xenium")
xenium.obj <- RunPCA(xenium.obj, npcs = 30, features = rownames(xenium.obj))
xenium.obj <- RunUMAP(xenium.obj, dims = 1:30)
xenium.obj <- FindNeighbors(xenium.obj, reduction = "pca", dims = 1:30)
xenium.obj <- FindClusters(xenium.obj, resolution = 0.3)
## Modularity Optimizer version 1.3.0 by Ludo Waltman and Nees Jan van Eck
## 
## Number of nodes: 36553
## Number of edges: 1341724
## 
## Running Louvain algorithm...
## Maximum modularity in 10 random starts: 0.9586
## Number of communities: 29
## Elapsed time: 5 seconds
cluster_col="seurat_clusters"
g = CellDimPlot(
  srt = xenium.obj, 
  group.by = cluster_col, 
  reduction = "UMAP", theme_use = "theme_blank",
  raster = FALSE,
  stat_plot_size = 3
) 
g 

FeaturePlot(xenium.obj, features = c("Cux2", "Bcl11b", "Foxp2", "Gad1", "Sst", "Gfap"))

ImageDimPlot(xenium.obj, cols = "polychrome", 
             size = 0.75)

# devtools::install_github("dmcable/spacexr", build_vignettes = FALSE)
library(spacexr)

query.counts <- GetAssayData(xenium.obj, assay = "Xenium", slot = "counts")
coords <- GetTissueCoordinates(xenium.obj[["fov"]], which = "centroids")
rownames(coords) <- coords$cell
coords$cell <- NULL
query <- SpatialRNA(coords, query.counts, colSums(query.counts))
# allen.corted.ref can be downloaded here:
# https://www.dropbox.com/s/cuowvm4vrf65pvq/allen_cortex.rds?dl=1
allen.cortex.ref <- readRDS("./../10X_Xenium_sample/allen_cortex.rds")
allen.cortex.ref <- UpdateSeuratObject(allen.cortex.ref)

Idents(allen.cortex.ref) <- "subclass"
# remove CR cells because there aren't enough of them for annotation
allen.cortex.ref <- subset(allen.cortex.ref, subset = subclass != "CR")
counts <- GetAssayData(allen.cortex.ref, assay = "RNA", slot = "counts")
cluster <- as.factor(allen.cortex.ref$subclass)
names(cluster) <- colnames(allen.cortex.ref)
nUMI <- allen.cortex.ref$nCount_RNA
names(nUMI) <- colnames(allen.cortex.ref)
nUMI <- colSums(counts)
levels(cluster) <- gsub("/", "-", levels(cluster))
reference <- Reference(counts, cluster, nUMI)
# run RCTD with many cores
RCTD <- create.RCTD(query, reference, max_cores = 8)
## 
##      Astro       Endo    L2-3 IT         L4      L5 IT      L5 PT      L6 CT 
##        368         94        982       1401        880        544        960 
##      L6 IT        L6b      Lamp5 Macrophage      Meis2         NP      Oligo 
##       1872        358       1122         51         45        362         91 
##       Peri      Pvalb   Serpinf1        SMC       Sncg        Sst        Vip 
##         32       1337         27         55        125       1741       1728 
##       VLMC 
##         67
RCTD <- run.RCTD(RCTD, doublet_mode = "doublet")
## [1] "gather_results: finished 1000"
## [1] "gather_results: finished 2000"
## [1] "gather_results: finished 3000"
## [1] "gather_results: finished 4000"
## [1] "gather_results: finished 5000"
## [1] "gather_results: finished 6000"
## [1] "gather_results: finished 7000"
## [1] "gather_results: finished 8000"
## [1] "gather_results: finished 9000"
## [1] "gather_results: finished 10000"
## [1] "gather_results: finished 11000"
## [1] "gather_results: finished 12000"
## [1] "gather_results: finished 13000"
## [1] "gather_results: finished 14000"
## [1] "gather_results: finished 15000"
## [1] "gather_results: finished 16000"
## [1] "gather_results: finished 17000"
## [1] "gather_results: finished 18000"
## [1] "gather_results: finished 19000"
## [1] "gather_results: finished 20000"
## [1] "gather_results: finished 21000"
## [1] "gather_results: finished 22000"
## [1] "gather_results: finished 23000"
## [1] "gather_results: finished 24000"
## [1] "gather_results: finished 25000"
## [1] "gather_results: finished 26000"
## [1] "gather_results: finished 27000"
## [1] "gather_results: finished 28000"
## [1] "gather_results: finished 29000"
## [1] "gather_results: finished 30000"
## [1] "gather_results: finished 31000"
annotations.df <- RCTD@results$results_df
annotations <- annotations.df$first_type
names(annotations) <- rownames(annotations.df)
xenium.obj$predicted.celltype <- annotations
keep.cells <- Cells(xenium.obj)[!is.na(xenium.obj$predicted.celltype)]
xenium.obj <- subset(xenium.obj, cells = keep.cells)
cluster_col="predicted.celltype"
Idents(xenium.obj) = xenium.obj@meta.data[,cluster_col]
markers = xenium.obj.markers %>%
  group_by(cluster) %>%
  dplyr::slice_max(avg_log2FC, n = 1) %>%
  as.data.frame() %>%
  pull(gene) %>%
  unique()
marker_COLORS = manual_colors
names(marker_COLORS) = markers
  
ImageDimPlot(xenium.obj, fov = "fov", molecules = markers, nmols = 20000) &
  scale_color_manual(values = marker_COLORS) 

cluster_COLORS = manual_colors
names(cluster_COLORS) = levels(Idents(xenium.obj))
cluster_COLORS = na.omit(cluster_COLORS)
g = CellDimPlot(
  srt = xenium.obj, 
  group.by = cluster_col, 
  reduction = "UMAP", theme_use = "theme_blank",
  raster = FALSE,
  stat_plot_size = 1
) &
  scale_color_manual(values = cluster_COLORS) &
  guides(color = guide_legend(override.aes = list(size=5,
                                                 alpha = 1),
                             title = "cluster",
                             ncol = 1))
g 

ggsave(paste0("./output/figure/",figure_dir,"/",data_name,"/CellDimPlot.pdf"), g, width=7, height=4, dpi=300)

print(xenium.obj)
## An object of class Seurat 
## 789 features across 31141 samples within 5 assays 
## Active assay: SCT (248 features, 248 variable features)
##  3 layers present: counts, data, scale.data
##  4 other assays present: Xenium, BlankCodeword, ControlCodeword, ControlProbe
##  2 dimensional reductions calculated: pca, umap
##  1 spatial field of view present: fov
g = ImageDimPlot(xenium.obj,
             fov = "fov", 
             size = 0.5,
             group.by = cluster_col)  &
  scale_fill_manual(values = cluster_COLORS)
g 

ggsave(paste0("./output/figure/",figure_dir,"/",data_name,"/ImageDimPlot_byClusters.pdf"), g, width=6, height=4, dpi=300)

2.2 Spatial neighborhood analysis (SNA, cell type level analysis)

n_perm = 100
neighbors.k_ = 30 # Number of neighbors to search
seed = 1234

start_time = Sys.time()
xenium.obj <- nhood_enrichment(
  xenium.obj,
  cluster_key = cluster_col, 
  neighbors.k = neighbors.k_, 
  connectivity_key = "nn", 
  transformation = TRUE,
  n_perms = n_perm, seed = seed, n_jobs = 4
)
end_time = Sys.time()
print("Elapsed time:")
## [1] "Elapsed time:"
difftime(end_time, start_time, units = "secs")
## Time difference of 36.60824 secs
mat = xenium.obj@misc[[paste0(cluster_col,"_nhood_enrichment")]]$zscore
colnames(mat) = gsub("^Cluster","",colnames(mat))
rownames(mat) = gsub("^Cluster","",rownames(mat))

pval_mat <- 1 - pnorm(mat)
# 行列をベクトルにし、一括で多重検定補正
# → 元の行列次元に再度変形
fdr_vec <- p.adjust(as.vector(pval_mat), method = "BH")
fdr_mat <- matrix(fdr_vec, nrow=nrow(mat), ncol=ncol(mat),
                  dimnames = dimnames(mat))
# --- 3) FDR<0.05 なら `*` を付与 ---
sig_mat <- ifelse(fdr_mat < 0.05, "**", ifelse(fdr_mat > 0.05 & fdr_mat < 0.1, "*", ""))

common_names <- intersect(rownames(mat), colnames(mat))
for (nm in common_names) {
  mat[nm, nm] <- NA
  sig_mat[nm, nm] <- ""
}

heatmap <- Heatmap(mat,
                   name = "Z-score",
                   col = colorRamp2(c(-2, 0, 2), c("#0072B5FF", "white", "#BC3C29FF")), 
                   show_row_names = TRUE, 
                   show_column_names = TRUE,  
                   cluster_rows = TRUE,  
                   cluster_columns = TRUE,  
                   #show_column_dend = FALSE,
                   #show_row_dend = FALSE,
                   row_title = "",  
                   column_title = paste0("Spatial Neigborhood Enrichment\n",data_name),
                   rect_gp = gpar(col = "black", lwd = 0.3),
                   na_col = "black",          # ← NA を黒色で塗りつぶす
                   column_names_gp = grid::gpar(fontsize = 10),
                   row_names_gp = grid::gpar(fontsize = 10),
                   # cell_fun で各セルに注釈を描く
                   cell_fun = function(j, i, x, y, width, height, fill) {
                     if(sig_mat[i, j] == "**") {
                       grid.text("**", 
                                 x = x,
                                 y = y - 0.2 * height,  # 中心より下にオフセット, 
                                 gp = gpar(fontsize = 15, col = "white", fontface = "bold"))
                     }
                     if(sig_mat[i, j] == "*") {
                       grid.text("*", 
                                 x = x,
                                 y = y - 0.2 * height,  # 中心より下にオフセット, 
                                 gp = gpar(fontsize = 15, col = "white", fontface = "bold"))
                     }
                   }
)

#pdf(paste0("./output/figure/",figure_dir,"/",data_name,"/SNA_heatmap.pdf"), width=4.5, height=5.5)
draw(heatmap, 
     merge_legend = TRUE,
     heatmap_legend_side = "bottom", 
     annotation_legend_side = "bottom")

#dev.off()

2.3 Spatial co-localization score (sCLA, cell-cell level analysis)

cluster_x <- "L6 IT"
cluster_y <- "L6 CT"
table(Idents(xenium.obj))
## 
##      Astro       Endo    L2-3 IT         L4      L5 IT      L5 PT      L6 CT 
##       5468       1773       4563       3679       1863       1896       2182 
##      L6 IT        L6b      Lamp5 Macrophage      Meis2         NP      Oligo 
##       1114        355        521        448         82        277       3892 
##       Peri      Pvalb   Serpinf1        SMC       Sncg        Sst        Vip 
##        239        604         56         24        351        223        114 
##       VLMC 
##       1417
radius_ = 30 # Radius to search for neighbors (µm, cell_type_2) around anchor cells (cell_type_1)

start_time = Sys.time()
cooccur_local_df <- cooccur_local(
  xenium.obj,
  cluster_key      = cluster_col,
  sample_key       = NULL,
  cluster_x        = cluster_x,
  cluster_y        = cluster_y,
  connectivity_key = "nn",
  neighbors.k      = neighbors.k_, 
  radius           = radius_,
  maxnsteps        = 15
)
end_time = Sys.time()
print("Elapsed time:")
## [1] "Elapsed time:"
difftime(end_time, start_time, units = "secs")
## Time difference of 7.286506 secs
colnames(cooccur_local_df) = gsub(" ", "_", colnames(cooccur_local_df))
summary(cooccur_local_df)
##  cooccur_local_L6_IT_L6_CT
##  Min.   :0.0000           
##  1st Qu.:0.0000           
##  Median :0.0000           
##  Mean   :0.0929           
##  3rd Qu.:0.0000           
##  Max.   :1.0787
xenium.obj = AddMetaData(xenium.obj, cooccur_local_df)

g = ImageFeaturePlot(xenium.obj, 
                     features = gsub(" ", "_", paste0("cooccur_local_",cluster_x,"_",cluster_y)), 
                     #dark.background = F,
                     cols = c("white", "red"))
g

ggsave(paste0("./output/figure/",figure_dir,"/",data_name,"/ImageFeaturePlot_",gsub(" ", "_", cluster_x),"_",gsub(" ", "_", cluster_y),".pdf"), g, width=6, height=4, dpi=300)
cluster_COLORS_ = cluster_COLORS[cluster_x]
g_x = ImageDimPlot(xenium.obj,
             fov = "fov", 
             size = 0.3,
             group.by = cluster_col)  &
  scale_fill_manual(values = cluster_COLORS_) &
  guides(fill = guide_legend(override.aes = list(size=5,
                                                 alpha = 1),
                             title = "cluster",
                             ncol = 1))
cluster_COLORS_ = cluster_COLORS[cluster_y]
g_y = ImageDimPlot(xenium.obj,
             fov = "fov", 
             size = 0.3,
             group.by = cluster_col)  &
  scale_fill_manual(values = cluster_COLORS_) &
  guides(fill = guide_legend(override.aes = list(size=5,
                                                 alpha = 1),
                             title = "cluster",
                             ncol = 1))
g_x + g_y

ggsave(paste0("./output/figure/",figure_dir,"/",data_name,"/ImageDimPlot_",gsub(" ", "_", cluster_x),"_",gsub(" ", "_", cluster_y),".pdf"), g_x + g_y, width=6, height=4, dpi=300)




3 sessionInfo

sessionInfo()
## R version 4.3.2 (2023-10-31)
## Platform: aarch64-apple-darwin20 (64-bit)
## Running under: macOS 15.3.2
## 
## Matrix products: default
## BLAS:   /Library/Frameworks/R.framework/Versions/4.3-arm64/Resources/lib/libRblas.0.dylib 
## LAPACK: /Library/Frameworks/R.framework/Versions/4.3-arm64/Resources/lib/libRlapack.dylib;  LAPACK version 3.11.0
## 
## locale:
## [1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
## 
## time zone: America/Denver
## tzcode source: internal
## 
## attached base packages:
##  [1] parallel  grid      stats4    stats     graphics  grDevices utils    
##  [8] datasets  methods   base     
## 
## other attached packages:
##  [1] spacexr_2.2.1               msigdbr_7.5.1              
##  [3] fgsea_1.28.0                randomcoloR_1.1.0.1        
##  [5] SCP_0.5.6                   gridExtra_2.3              
##  [7] RANN_2.6.1                  ComplexHeatmap_2.18.0      
##  [9] CellChat_2.1.2              bigmemory_4.6.4            
## [11] scales_1.3.0                circlize_0.4.15            
## [13] ggraph_2.1.0                Matrix_1.6-5               
## [15] pheatmap_1.0.12             ggalluvial_0.12.5          
## [17] StabMap_0.1.8               igraph_1.6.0               
## [19] biomaRt_2.58.2              MOFAdata_1.18.0            
## [21] MOFA2_1.13.0                scDblFinder_1.16.0         
## [23] SingleCellExperiment_1.24.0 SummarizedExperiment_1.32.0
## [25] Biobase_2.62.0              GenomicRanges_1.54.1       
## [27] GenomeInfoDb_1.38.2         IRanges_2.36.0             
## [29] S4Vectors_0.40.2            BiocGenerics_0.48.1        
## [31] MatrixGenerics_1.14.0       matrixStats_1.2.0          
## [33] ggrastr_1.0.2               harmony_1.2.0              
## [35] Rcpp_1.0.11                 dplyr_1.1.4                
## [37] magrittr_2.0.3              scCustomize_2.0.1          
## [39] ggpubr_0.6.0                ggsci_3.0.0                
## [41] ggrepel_0.9.4               ggplot2_3.4.4              
## [43] patchwork_1.1.3             Seurat_5.0.0               
## [45] SeuratObject_5.0.2          sp_2.1-2                   
## [47] BiocStyle_2.30.0           
## 
## loaded via a namespace (and not attached):
##   [1] ica_1.0-3                     plotly_4.10.3                
##   [3] scater_1.30.1                 rematch2_2.1.2               
##   [5] zlibbioc_1.48.0               tidyselect_1.2.0             
##   [7] bit_4.0.5                     doParallel_1.0.17            
##   [9] clue_0.3-65                   lattice_0.21-9               
##  [11] rjson_0.2.21                  blob_1.2.4                   
##  [13] stringr_1.5.1                 rngtools_1.5.2               
##  [15] S4Arrays_1.2.0                png_0.1-8                    
##  [17] cli_3.6.2                     ggplotify_0.1.2              
##  [19] registry_0.5-1                goftest_1.2-3                
##  [21] textshaping_0.3.7             BiocIO_1.12.0                
##  [23] glmGamPoi_1.14.0              bluster_1.12.0               
##  [25] purrr_1.0.2                   basilisk.utils_1.14.1        
##  [27] BiocNeighbors_1.20.1          ggnetwork_0.5.12             
##  [29] Signac_1.14.0                 shadowtext_0.1.2             
##  [31] uwot_0.1.16                   curl_5.2.0                   
##  [33] tidytree_0.4.6                mime_0.12                    
##  [35] evaluate_0.23                 leiden_0.4.3.1               
##  [37] V8_6.0.0                      stringi_1.8.3                
##  [39] backports_1.4.1               slingshot_2.10.0             
##  [41] XML_3.99-0.16                 lubridate_1.9.3              
##  [43] httpuv_1.6.13                 AnnotationDbi_1.64.1         
##  [45] paletteer_1.5.0               clusterProfiler_4.10.0       
##  [47] rappdirs_0.3.3                splines_4.3.2                
##  [49] RcppRoll_0.3.0                corrplot_0.92                
##  [51] sctransform_0.4.1             ggbeeswarm_0.7.2             
##  [53] arrow_17.0.0.1                DBI_1.2.0                    
##  [55] HDF5Array_1.30.0              jquerylib_0.1.4              
##  [57] withr_2.5.2                   systemfonts_1.0.5            
##  [59] enrichplot_1.22.0             xgboost_1.7.6.1              
##  [61] lmtest_0.9-40                 ggnewscale_0.4.9             
##  [63] tidygraph_1.3.0               rtracklayer_1.62.0           
##  [65] BiocManager_1.30.22           htmlwidgets_1.6.4            
##  [67] fs_1.6.3                      princurve_2.1.6              
##  [69] statnet.common_4.9.0          labeling_0.4.3               
##  [71] SparseArray_1.2.3             reticulate_1.35.0            
##  [73] zoo_1.8-12                    XVector_0.42.0               
##  [75] knitr_1.45                    network_1.18.2               
##  [77] timechange_0.2.0              foreach_1.5.2                
##  [79] fansi_1.0.6                   data.table_1.16.0            
##  [81] ggtree_3.10.0                 rhdf5_2.46.1                 
##  [83] R.oo_1.25.0                   RSpectra_0.16-1              
##  [85] irlba_2.3.5.1                 fastDummies_1.7.3            
##  [87] gridGraphics_0.5-1            ellipsis_0.3.2               
##  [89] lazyeval_0.2.2                yaml_2.3.8                   
##  [91] survival_3.5-7                scattermore_1.2              
##  [93] BiocVersion_3.18.1            crayon_1.5.2                 
##  [95] RcppAnnoy_0.0.21              RColorBrewer_1.1-3           
##  [97] tidyr_1.3.0                   progressr_0.14.0             
##  [99] tweenr_2.0.2                  later_1.3.2                  
## [101] ggridges_0.5.5                codetools_0.2-19             
## [103] GlobalOptions_0.1.2           KEGGREST_1.42.0              
## [105] Rtsne_0.17                    shape_1.4.6                  
## [107] limma_3.58.1                  Rsamtools_2.18.0             
## [109] filelock_1.0.3                pkgconfig_2.0.3              
## [111] xml2_1.3.6                    spatstat.univar_3.1-2        
## [113] GenomicAlignments_1.38.0      aplot_0.2.2                  
## [115] ape_5.7-1                     spatstat.sparse_3.1-0        
## [117] viridisLite_0.4.2             gridBase_0.4-7               
## [119] xtable_1.8-4                  highr_0.10                   
## [121] car_3.1-2                     plyr_1.8.9                   
## [123] httr_1.4.7                    tools_4.3.2                  
## [125] globals_0.16.2                beeswarm_0.4.0               
## [127] broom_1.0.5                   nlme_3.1-163                 
## [129] HDO.db_0.99.1                 dbplyr_2.4.0                 
## [131] assertthat_0.2.1              digest_0.6.33                
## [133] bookdown_0.37                 dir.expiry_1.10.0            
## [135] farver_2.1.1                  reshape2_1.4.4               
## [137] TrajectoryUtils_1.10.0        yulab.utils_0.1.2            
## [139] viridis_0.6.4                 glue_1.6.2                   
## [141] cachem_1.0.8                  BiocFileCache_2.10.1         
## [143] polyclip_1.10-6               UpSetR_1.4.0                 
## [145] proxyC_0.3.4                  generics_0.1.3               
## [147] Biostrings_2.70.1             presto_1.0.0                 
## [149] parallelly_1.36.0             statmod_1.5.0                
## [151] R.cache_0.16.0                ragg_1.2.7                   
## [153] RcppHNSW_0.5.0                ScaledMatrix_1.10.0          
## [155] carData_3.0-5                 pbapply_1.7-2                
## [157] spam_2.10-0                   gson_0.1.0                   
## [159] dqrng_0.3.2                   utf8_1.2.4                   
## [161] basilisk_1.14.1               graphlayouts_1.0.2           
## [163] ggsignif_0.6.4                shiny_1.8.0                  
## [165] GenomeInfoDbData_1.2.11       R.utils_2.12.3               
## [167] rhdf5filters_1.14.1           RCurl_1.98-1.13              
## [169] memoise_2.0.1                 rmarkdown_2.25               
## [171] R.methodsS3_1.8.2             future_1.33.1                
## [173] svglite_2.1.3                 Cairo_1.6-2                  
## [175] bigmemory.sri_0.1.8           spatstat.data_3.1-4          
## [177] rstudioapi_0.15.0             cluster_2.1.4                
## [179] janitor_2.2.0                 spatstat.utils_3.1-2         
## [181] hms_1.1.3                     fitdistrplus_1.1-11          
## [183] munsell_0.5.0                 cowplot_1.1.2                
## [185] colorspace_2.1-0              FNN_1.1.3.2                  
## [187] quadprog_1.5-8                rlang_1.1.2                  
## [189] DelayedMatrixStats_1.24.0     sparseMatrixStats_1.14.0     
## [191] dotCall64_1.1-1               ggforce_0.4.1                
## [193] scuttle_1.12.0                xfun_0.41                    
## [195] coda_0.19-4                   sna_2.7-2                    
## [197] iterators_1.0.14              abind_1.4-5                  
## [199] interactiveDisplayBase_1.40.0 GOSemSim_2.28.0              
## [201] tibble_3.2.1                  treeio_1.26.0                
## [203] Rhdf5lib_1.24.1               bitops_1.0-7                 
## [205] promises_1.2.1                scatterpie_0.2.1             
## [207] RSQLite_2.3.4                 qvalue_2.34.0                
## [209] DelayedArray_0.28.0           GO.db_3.18.0                 
## [211] compiler_4.3.2                forcats_1.0.0                
## [213] prettyunits_1.2.0             beachmat_2.18.0              
## [215] listenv_0.9.0                 AnnotationHub_3.10.0         
## [217] edgeR_4.0.3                   BiocSingular_1.18.0          
## [219] tensor_1.5                    MASS_7.3-60                  
## [221] progress_1.2.3                uuid_1.1-1                   
## [223] BiocParallel_1.36.0           babelgene_22.9               
## [225] spatstat.random_3.3-2         R6_2.5.1                     
## [227] fastmap_1.1.1                 fastmatch_1.1-4              
## [229] rstatix_0.7.2                 vipor_0.4.7                  
## [231] ROCR_1.0-11                   rsvd_1.0.5                   
## [233] gtable_0.3.4                  KernSmooth_2.23-22           
## [235] miniUI_0.1.1.1                deldir_2.0-2                 
## [237] htmltools_0.5.7               RcppParallel_5.1.7           
## [239] bit64_4.0.5                   spatstat.explore_3.3-4       
## [241] lifecycle_1.0.4               ggprism_1.0.4                
## [243] restfulr_0.0.15               sass_0.4.8                   
## [245] vctrs_0.6.5                   spatstat.geom_3.3-5          
## [247] snakecase_0.11.1              DOSE_3.28.2                  
## [249] scran_1.30.0                  NMF_0.26                     
## [251] ggfun_0.1.3                   future.apply_1.11.1          
## [253] bslib_0.6.1                   pillar_1.9.0                 
## [255] moments_0.14.1                magick_2.8.2                 
## [257] metapod_1.10.1                locfit_1.5-9.8               
## [259] jsonlite_1.8.8                GetoptLong_1.0.5